#include "ReservedJobs.h"
#include "CMSInterface.h"
#include "ControllerConnection.h"

ReservedJobs ReservedJobs::gReservedJobs;



void ReservedJobs::Start()
{
	gReservedJobs.activate();
}

void ReservedJobs::push(_RESERVED_TYPE reserved_type , const ReservedInfo& info)
{
	if(gReservedJobs.stop)
		return;

	switch(reserved_type)
	{
	case _SUCCEEDED_JOB:
		gReservedJobs.jobLock.acquire();

		gReservedJobs.vecSucceededJobs.push_back(info);

		gReservedJobs.jobLock.release();
		break;
	case _FAILED_JOB:
		gReservedJobs.jobLock.acquire();

		gReservedJobs.vecFailedJobs.push_back(info);

		gReservedJobs.jobLock.release();
		break;
	}
}

void ReservedJobs::push(_RESERVED_TYPE reserved_type , const _JOB_INFO& job_info)
{
	push(reserved_type , ReservedInfo(job_info));
}

void ReservedJobs::push(_RESERVED_TYPE reserved_type , const _JOB_INFO& job_info , const _WORK_RESULT& result )
{
	push(reserved_type , ReservedInfo(job_info , result));
}

void ReservedJobs::move(std::vector<ReservedInfo>& vecSucceeded , std::vector<ReservedInfo>& vecFailed)
{
		gReservedJobs.jobLock.acquire();

		if(gReservedJobs.vecSucceededJobs.size() > 0)
		{
			vecSucceeded = gReservedJobs.vecSucceededJobs;
			gReservedJobs.vecSucceededJobs.clear();
		}

		if(gReservedJobs.vecFailedJobs.size() > 0)
		{
			vecFailed = gReservedJobs.vecFailedJobs;
			gReservedJobs.vecFailedJobs.clear();
		}

		gReservedJobs.jobLock.release();
}

void ReservedJobs::cancel(_RESERVED_TYPE reserved_type , const ReservedInfo& info)
{
	if(gReservedJobs.stop)
		return;

	switch(reserved_type)
	{
	case _SUCCEEDED_JOB:

		gReservedJobs.jobLock.acquire();

		gReservedJobs.vecSucceededJobs.push_back(info);

		gReservedJobs.jobLock.release();
		break;
	case _FAILED_JOB:
		gReservedJobs.jobLock.acquire();

		gReservedJobs.vecFailedJobs.push_back(info);

		gReservedJobs.jobLock.release();
		break;
	}

}




int ReservedJobs::svc(void)
{
	std::vector<ReservedInfo> v;
	char buf[1024];

	while(!stop)
	{
		std::vector<ReservedInfo> vecSucceeded;
		std::vector<ReservedInfo> vecFailed;

		std::vector<std::string> vecJobId;
		
		ReservedJobs::move(vecSucceeded , vecFailed);
	
		for(int i = 0 ; i < vecSucceeded.size() ; i ++)
		{
			if(!CMSInterface::SucceededJob(vecSucceeded[i]))
			{
				sprintf(buf , "succeededJobs FAILD %s" , vecSucceeded[i].job_info.GetJobId().c_str());
				LOG::PushProcessLog(_REQUIRED , buf); 

				ReservedJobs::cancel(_SUCCEEDED_JOB , vecSucceeded[i]);
			}
			else
			{
				vecJobId.push_back(vecSucceeded[i].job_info.GetJobId());

				sprintf(buf , "succeedecJobs SUCCEEDED %s" , vecSucceeded[i].job_info.GetJobId().c_str());
			}

			printf("%s\n" , buf);
		}

		for(int i = 0 ; i < vecFailed.size() ; i ++)
		{
			if(!CMSInterface::FailedJob(vecFailed[i]))
			{
				sprintf(buf, "failedJobs FAILED %s" , vecFailed[i].job_info.GetJobId().c_str());
				LOG::PushProcessLog(_ERROR , buf);

				ReservedJobs::cancel(_FAILED_JOB , vecFailed[i]);

			}
			else
			{
				vecJobId.push_back(vecFailed[i].job_info.GetJobId());

				sprintf(buf , "failedJobs SUCCEEDED %s" , vecFailed[i].job_info.GetJobId().c_str());

			}
			printf("%s\n" , buf);

		}

		if(Renderer::g_worker && vecJobId.size() > 0)
		{
			Json::Value root;
			Json::Value list;

			for(int i = 0 ; i < vecJobId.size() ; i ++)
			{
				list.append( vecJobId[i]);
			}

			root["jobIdList"] = list;

			PACKET_END_LIST el(root);


			Renderer::g_worker->Send(el);
		}


		if( vecJobId.size() == 0 && !stop)
		{
			sleep(Settings::GetSettings()->QUEUE_DELAY);
		}
	
	}

	return 0;

}


JOB_MONITOR JOB_MONITOR::g_Monitor;

void JOB_MONITOR::Insert(const bool start , const std::string& job_id)
{
	if(start)
	{
		jobLock.acquire();
		m_vecStartData.push_back(job_id);
		jobLock.release();
	}
	else
	{
		jobLock.acquire();
		m_vecEndData.push_back(job_id);
		jobLock.release();
	}

}

void JOB_MONITOR::StartJob(_JOB_INFO & job_info)
{
	if(!g_Monitor.m_bStop)
	{
		g_Monitor.Insert(true , job_info.GetJobId() );
	}
}

void JOB_MONITOR::EndJob(_JOB_INFO & job_info , _WORK_RESULT& result)
{
	if(!g_Monitor.m_bStop)
	{
		
		if(result.IsSuccess())
			ReservedJobs::push(_SUCCEEDED_JOB , job_info , result);
		else
			ReservedJobs::push(_FAILED_JOB , job_info , result);


		g_Monitor.Insert(false , job_info.GetJobId());
	}
}


void JOB_MONITOR::move(std::vector<std::string>& vecStart , std::vector<std::string>& vecEnd)
{
		g_Monitor.jobLock.acquire();

		if(g_Monitor.m_vecStartData.size() > 0)
		{
			vecStart = g_Monitor.m_vecStartData;
			g_Monitor.m_vecStartData.clear();
		}

		if(g_Monitor.m_vecEndData.size() > 0)
		{
			vecEnd = g_Monitor.m_vecEndData;
			g_Monitor.m_vecEndData.clear();
		}

		g_Monitor.jobLock.release();
}

void JOB_MONITOR::cancel(const bool start , const std::vector<std::string>& vec)
{
	if(vec.size() == 0 || g_Monitor.m_bStop)
		return;

	if(start)
	{
		g_Monitor.jobLock.acquire();

		g_Monitor.m_vecStartData.insert(g_Monitor.m_vecStartData.begin() , vec.begin() , vec.end());

		g_Monitor.jobLock.release();
	}
	else
	{
		g_Monitor.jobLock.acquire();

		g_Monitor.m_vecEndData.insert(g_Monitor.m_vecEndData.begin() , vec.begin() , vec.end());

		g_Monitor.jobLock.release();
	}

}



int JOB_MONITOR::svc()
{

	while(!m_bStop)
	{

		std::vector<std::string> vStart;
		std::vector<std::string> vEnd;

		move(vStart , vEnd);

		unsigned int total = 0;

		if(vStart.size() > 0)
		{
			total += vStart.size();

			DBInterface::DelJobList(vStart);

			for(int i = 0 ; i < vStart.size() ; i ++)
				DBInterface::AddJob(Settings::GetSettings()->RENDERER_ID , Settings::GetSettings()->LOCAL_ADDR , vStart[i]); 			

		}

		if(vEnd.size() > 0)
		{
			total += vEnd.size();

			DBInterface::DelJobList(vEnd);
		}


		if(total == 0 && !m_bStop)
		{
			sleep(Settings::GetSettings()->QUEUE_DELAY);
		}

	}

	return 0;
}

